package yxy.apple.util;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;

public class URLUtility {
	public static HashMap<String, String> parse(String query) {
		if (query != null) {
			HashMap<String, String> buffer = new HashMap<String, String>();
			String[] items = query.split("\\&");
			for (String item : items) {
				String[] kv = item.split("\\=", 2);
				if (kv.length >= 2) {
					String key = kv[0];
					String value = kv[1];
					buffer.put(key, value);
				} else if (kv.length >= 1) {
					String key = kv[0];
					buffer.put(key, null);
				}
			}
			return buffer;
		} else {
			return null;
		}
	}

	public static String toQueryString(HashMap<String, String> form, boolean encode) {
		if (form == null) {
			return null;
		}
		StringBuffer buffer = new StringBuffer();
		Iterator<String> keys = form.keySet().iterator();
		while (keys.hasNext()) {
			String key = keys.next();
			if (key != null) {
				String value = form.get(key);
				if (value == null) {
					value = "";
				}
				buffer.append(key);
				buffer.append("=");
				if (encode) {
					buffer.append(encodeWithUTF8Encoding(value));
				} else {
					buffer.append(value);
				}
				if (keys.hasNext()) {
					buffer.append("&");
				}
			}
		}
		return buffer.toString();
	}

	public static String encodeWithUTF8Encoding(String string) {
		try {
			return URLEncoder.encode(string, "UTF-8");
		} catch (Exception e) {
			return null;
		}
	}

	public static String decodeWithUTF8Encoding(String string) {
		try {
			return URLDecoder.decode(string, "UTF-8");
		} catch (Exception e) {
			return null;
		}
	}

	public static class URLBuilder {
		private Hashtable<String, String> parameters = new Hashtable<>();
		public String scheme = null;
		public String host = null;
		public String path = null;

		public URLBuilder(String scheme, String host, String path) {
			this.scheme = scheme;
			this.host = host;
			this.path = path;
		}

		/**
		 * 添加parameter，认为key和value均未进行urlencode处理，添加时会自动附加urlencode处理
		 * 
		 * @param key
		 * @param value
		 */
		public void addParameter(String key, String value) {
			this.addParameter(key, value, false);
		}

		/**
		 * 添加parameter
		 * 
		 * @param key
		 * @param value
		 * @param encoded
		 *            是否已经对key和value进行过urlencode处理，如果已处理则此方法不会再次进行编码
		 */
		public void addParameter(String key, String value, boolean encoded) {
			if (key != null && value != null) {
				String k = key;
				String v = value;
				if (!encoded) {
					k = URLUtility.encodeWithUTF8Encoding(key);
					v = URLUtility.encodeWithUTF8Encoding(value);
				}
				this.parameters.put(k, v);
			}
		}

		public String getParameter(String key) {
			return this.getParameter(key, false);
		}

		public String getParameter(String key, boolean encoded) {
			if (key != null) {
				String k = key;
				if (!encoded) {
					k = URLUtility.encodeWithUTF8Encoding(k);
				}
				String v = this.parameters.get(k);
				if (v != null) {
					return URLUtility.decodeWithUTF8Encoding(v);
				} else {
					return null;
				}
			} else {
				return null;
			}
		}

		/**
		 * 移除parameter <br />
		 * 认为key未做urlencode，会在查询并移除parameter前先多key进行一次编码
		 * 
		 * @param key
		 */
		public String removeParameter(String key) {
			return this.removeParameter(key, false);
		}

		/**
		 * 
		 * @param key
		 * @param encoded
		 *            是否已经对key和value进行过urlencode处理，如果已处理则此方法不会再次进行编码
		 */
		public String removeParameter(String key, boolean encoded) {
			if (key != null) {
				String k = key;
				if (!encoded) {
					k = URLUtility.encodeWithUTF8Encoding(k);
				}
				String v = this.parameters.remove(k);
				if (v != null) {
					return URLUtility.decodeWithUTF8Encoding(v);
				} else {
					return null;
				}
			} else {
				return null;
			}
		}

		public String query() {
			Enumeration<String> keys = this.parameters.keys();
			if (keys.hasMoreElements()) {
				StringBuffer buffer = new StringBuffer();
				while (true) {
					String key = keys.nextElement();
					String value = this.parameters.get(key);
					buffer.append(key);
					buffer.append("=");
					buffer.append(value);
					if (keys.hasMoreElements()) {
						buffer.append("&");
					} else {
						break;
					}
				}
				return buffer.toString();
			} else {
				return null;
			}
		}

		public String build() {
			StringBuffer buffer = new StringBuffer();
			buffer.append(this.scheme);
			buffer.append("://");
			buffer.append(this.host);
			buffer.append(this.path);
			String query = this.query();
			if (query != null) {
				buffer.append("?");
				buffer.append(query);
			}
			return buffer.toString();
		}
	}
}
